use once_cell::sync::Lazy;
use rbatis::rbatis::RBatis;
use serde::Deserialize;
use serde_yaml;
use std::{fs::File, io::Read};

#[derive(Debug, Deserialize)]
pub struct Config {
    pub server: Server,
    pub attach: Attach,
    pub view: View,
}
#[derive(Debug, Deserialize)]
pub struct Server {
    pub debug: bool,
    pub is_embed: bool,
    pub rust_log: String,
    pub admin_prefix: String,
    pub admin_id: u16,
    pub default_avatar: String,
    pub address: String,
    pub database_url: String,
    pub redis_url: String,
}

#[derive(Debug, Deserialize)]
pub struct Attach {
    pub attach_path: String,
    pub upload_path: String,
    pub upload_url: String,
}

#[derive(Debug, Deserialize)]
pub struct View {
    pub blog_tpl_path: String,
    pub blog_theme: String,
}

const CFG_FILE: &str = "assert/config/config.yaml";
// 只要是配置文件中的配置项，都可以通过这个结构体来获取，
// 只要读取一次值后保存到内存，一直可供使用
pub static CFG: Lazy<Config> = Lazy::new(self::Config::init);
pub static DB: Lazy<RBatis> = Lazy::new(|| init_db());

impl Config {
    pub fn init() -> Self {
        let mut file = match File::open(CFG_FILE) {
            Ok(f) => f,
            Err(e) => panic!("不存在配置文件：{}，错误信息：{}", CFG_FILE, e),
        };
        let mut cfg_contents = String::new();
        match file.read_to_string(&mut cfg_contents) {
            Ok(s) => s,
            Err(e) => panic!("读取配置文件失败，错误信息：{}", e),
        };
        serde_yaml::from_str(&cfg_contents).expect("解析配置文件错误")
    }
}

pub fn init_db() -> RBatis {
    let rb = RBatis::new();
    rb.init(rbdc_mysql::driver::MysqlDriver {}, &CFG.server.database_url)
        .unwrap();
    rb
}

#[test]
fn test_config() {
    println!("server = {:#?}", CFG.server);
    println!("attach = {:#?}", CFG.attach);
    println!("view = {:#?}", CFG.view);
}

#[tokio::test]
async fn test_database() {
    let sql_file = "blog.sql";
    let sql = std::fs::read_to_string(sql_file).unwrap();
    let _ = DB.exec(&sql, vec![]).await;
}